from fastapi import HTTPException, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from pydantic import ValidationError
from app.exception import CodeException
from app.exception.error_code import ErrorCode
from app.schemas.rr import RR
import logging
import traceback
import sys

logger = logging.getLogger(__name__)
class ExceptionHandler:
    """异常处理器类，提供统一的异常处理方法"""
    
    # 获取日志记录器
    
    @staticmethod
    def create_error_response(message: str, code: int, status_code: int):
        """创建统一格式的错误响应
        
        Args:
            message: 错误消息
            code: 错误码
            status_code: HTTP状态码
        
        Returns:
            JSONResponse: 格式化的错误响应
        """
        error_response = RR.fail(message, code=code)
        return JSONResponse(status_code=status_code, content=error_response.dict())
    
    @staticmethod
    async def validation_exception_handler(request: Request, exc: RequestValidationError):
        """RequestValidationError处理 - 专门处理请求验证错误"""
        # 提取验证错误详情，构建友好的错误信息
        error_details = []
        for error in exc.errors():
            field_path = ".".join(str(loc) for loc in error["loc"])
            error_details.append(f"{field_path}: {error['msg']}")
        
        error_message = " | ".join(error_details)
        logger.warning(f"Validation error in request {request.url.path}: {error_message}")
        
        # 构建标准化响应格式
        response_content = {
            "code": ErrorCode.INVAILD_PARAM_EXCEPTION,
            "message": "Invalid request parameters",
            "data": error_details,
            "timestamp": "auto",  # 前端可以自动填充时间戳
            "path": request.url.path,
            "method": request.method
        }
        
        return JSONResponse(
            status_code=422,
            content=response_content
        )
    
    @staticmethod
    async def http_exception_handler(request: Request, exc: HTTPException):
        """HTTPException处理 - 专门处理FastAPI的HTTP异常"""
        # 404等常见错误的特殊处理
        if exc.status_code == 404:
            logger.warning(f"Resource not found: {request.url.path}")
            return JSONResponse(
                status_code=404,
                content={
                    "code": ErrorCode.RESOURCE_NOT_FOUND,
                    "message": "Resource not found",
                    "data": None
                }
            )
        
        logger.warning(f"HTTP error {exc.status_code} in request {request.url.path}: {exc.detail}")
        
        # 构建标准化响应格式
        response_content = {
            "code": exc.status_code,
            "message": exc.detail,
            "data": None,
            "timestamp": "auto",
            "path": request.url.path,
            "method": request.method
        }
        
        return JSONResponse(
            status_code=exc.status_code,
            content=response_content
        )
    
    @staticmethod
    async def code_exception_handler(request: Request, exc: CodeException):
        """CodeException处理 - 专门处理业务异常"""
        logger.info(f"Business error in request {request.url.path}: {exc.code} - {exc.err_msg}")
        
        # 可以根据不同的业务错误码映射不同的HTTP状态码
        http_status_code = 400  # 默认400
        if exc.code == ErrorCode.NOT_PERMISSION:
            http_status_code = 403
        elif exc.code == ErrorCode.NO_LOGIN:
            http_status_code = 401
        
        # 构建标准化响应格式
        response_content = {
            "code": exc.code,
            "message": getattr(exc, 'message', exc.err_msg),
            "data": getattr(exc, 'data', None),
            "timestamp": "auto",
            "path": request.url.path,
            "method": request.method
        }
        
        return JSONResponse(
            status_code=http_status_code,
            content=response_content
        )
    
    @staticmethod
    async def global_exception_handler(request: Request, exc: Exception):
        """全局异常处理 - 处理所有其他异常，包括验证错误"""
        # 获取详细的异常堆栈信息
        exc_type, exc_value, exc_traceback = sys.exc_info()
        stack_trace = ''.join(traceback.format_tb(exc_traceback))
        
        # 根据日志级别决定是否记录完整堆栈
        if logger.level <= logging.DEBUG:
            logger.error(
                f"Unhandled error in request {request.url.path}\n"\
                f"Error type: {exc_type.__name__}\n"\
                f"Error message: {str(exc)}\n"\
                f"Stack trace:\n{stack_trace}"
            )
        else:
            logger.error(
                f"Unhandled error in request {request.url.path}: {exc_type.__name__} - {str(exc)}"
            )
        
        # 构建标准化响应格式
        response_content = {
            "code": 500,
            "message": "Internal Server Error",
            "data": str(exc) if logger.level <= logging.DEBUG else None,
            "timestamp": "auto",
            "path": request.url.path,
            "method": request.method
        }
        
        return JSONResponse(
            status_code=500,
            content=response_content
        )


# 为了向后兼容，保留原来的函数引用
validation_exception_handler = ExceptionHandler.validation_exception_handler
http_exception_handler = ExceptionHandler.http_exception_handler
code_exception_handler = ExceptionHandler.code_exception_handler
global_exception_handler = ExceptionHandler.global_exception_handler
create_error_response = ExceptionHandler.create_error_response